package com.google.code.netbuilder.dal.entities;

import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.xml.bind.annotation.*;


@XmlRootElement(name = "port")
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
@Table(name = "port")
@SequenceGenerator(sequenceName = "port_seq", name = "port_seq", initialValue = 1, allocationSize = 100)
public class Port extends ManagedObject {

	private static final long serialVersionUID = 3446212088246137881L;
	@XmlElement(name = "inner_connected_port")
    @XmlIDREF
    @OneToOne
    @JoinTable(name = "internal_connection",
            joinColumns =
            @JoinColumn(name = "to_port_id"),
            inverseJoinColumns =
            @JoinColumn(name = "from_port_id"))
    private Port innerConnectedPort;
    @XmlElement(name = "outer_connected_port")
    @XmlIDREF
    @OneToOne
    @JoinTable(name = "wire",
            joinColumns =
            @JoinColumn(name = "to_port_id"),
            inverseJoinColumns =
            @JoinColumn(name = "from_port_id"))
    private Port outerConnectedPort;
    @XmlTransient
    @OneToOne(mappedBy="fromPort")
    private Wire wire;
    @XmlTransient
    @OneToOne
    @JoinColumn(name = "equipment_id")
    private Equipment equipment;

    public Port getInnerConnectedPort() {
        return innerConnectedPort;
    }

    public void setInnerConnectedPort(Port innerConnectedPort) {
        this.innerConnectedPort = innerConnectedPort;
    }

    public Port getOuterConnectedPort() {
        return outerConnectedPort;
    }

    public void setOuterConnectedPort(Port outerConnectedPort) {
        this.outerConnectedPort = outerConnectedPort;
    }

    public Wire getWire() {
        return wire;
    }

    public void setWire(Wire wire) {
        this.wire = wire;
    }

    public Equipment getEquipment() {
        return equipment;
    }

    public void setEquipment(Equipment equipment) {
        this.equipment = equipment;
    }
    
    @Override
    public boolean equals(Object ob)
    {
        if(ob == null)
        {
            return false;
        }
        
        if(!(ob instanceof Port))
        {
            return false;
        }
        Port castedOb = (Port) ob;
        
        boolean innerCompare = false;
        boolean outerCompare = false;
        
        if(innerConnectedPort == null || castedOb.getInnerConnectedPort() == null)
        {
            innerCompare = (innerConnectedPort == castedOb.getInnerConnectedPort());
        }
        else
        {
            innerCompare = (innerConnectedPort.getId() == castedOb.getInnerConnectedPort().getId());
        }
        
        if(outerConnectedPort == null || castedOb.getOuterConnectedPort() == null)
        {
            outerCompare = (outerConnectedPort == castedOb.getOuterConnectedPort());
        }
        else
        {
            outerCompare = (outerConnectedPort.getId() == castedOb.getOuterConnectedPort().getId());
        }
        return super.equals(ob) && innerCompare && outerCompare;
    }
    
    @Override
    public String toString() {
        return "Port{" + super.toString()
                + ", innerConnectedPort=" + (innerConnectedPort != null ? innerConnectedPort.getId() : "null")
                + ", outerConnectedPort=" + (outerConnectedPort != null ? outerConnectedPort.getId() : "null") + '}';
    }
    
    public boolean isFree() {
        
        return (outerConnectedPort == null);
    }
    
    public boolean isOccupied()
    {
        return (outerConnectedPort != null);
    }
}
